home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / popi / popi.lha / popi / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-15  |  14.5 KB  |  577 lines

  1.  
  2. /*  @(#)io.c 1.5 92/04/16
  3.  *
  4.  *  File handling routines used by the popi program.
  5.  *
  6.  *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
  7.  *  This version is based on the code in his Prentice Hall book,
  8.  *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
  9.  *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
  10.  *
  11.  *  Permission is given to distribute these extensions, as long as these
  12.  *  introductory messages are not removed, and no monies are exchanged.
  13.  *
  14.  *  No responsibility is taken for any errors or inaccuracies inherent
  15.  *  either to the comments or the code of this program, but if reported
  16.  *  (see README file) then an attempt will be made to fix them.
  17.  */
  18.  
  19.  
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <errno.h>
  23. #include <ctype.h>
  24. #include "popi.h"
  25. #include "libpbm.h"
  26.  
  27. #if           unix || AMIGA
  28. #define  RMODE  "r"
  29. #define  WMODE  "w"
  30. #else   /* ! (unix || AMIGA) */
  31. #define  RMODE  "rb"
  32. #define  WMODE  "wb"
  33. #endif  /*    unix || AMIGA */
  34.  
  35. #if  defined(unix)
  36. static bool IsPopen = FALSE ;
  37. #endif  /* unix */
  38.  
  39. int nimages = 2 ;
  40.  
  41.  
  42. pixel_t **
  43. ImgAlloc(xsize, ysize, ncolors)
  44. int xsize, ysize, ncolors ;
  45. {
  46.   int color ;
  47.   pixel_t **img ;
  48.  
  49.   noerr = TRUE ;
  50.   img = (pixel_t **)
  51.         LINT_CAST(Emalloc((unsigned) ncolors * sizeof(pixel_t *))) ;
  52.   if (img == 0) return((pixel_t **) 0) ;
  53.   for (color = 0; color < ncolors; color++)
  54.     img[color] = (pixel_t *)
  55.              LINT_CAST(Emalloc((unsigned) xsize * ysize * sizeof (pixel_t))) ;
  56.  
  57.   if (!noerr)
  58.     {
  59.  
  60. /* Run out of memory; free what we have allocated */
  61.  
  62.       for (color = 0; color < ncolors; color++)
  63.         if (img[color]) free((char *) img[color]) ;
  64.       return((pixel_t **) 0) ;
  65.     }
  66.   return(img) ;
  67. }
  68.  
  69.  
  70. void
  71. ImgFree(img)
  72. struct SRC *img ;
  73. {
  74.   int color ;
  75.  
  76.   free(img->str) ;
  77.   img->str = (char *) 0 ;
  78.  
  79.   for (color = 0; color < img->ncolors; color++)
  80.     free((char *) img->pix[color]) ;
  81.   free((char *) img->pix) ;
  82.   img->pix = (pixel_t **) NULL ;
  83. }
  84.  
  85.  
  86. void
  87. Efclose(stream)
  88. FILE *stream ;
  89. {
  90. #ifdef  unix
  91.   if (IsPopen)
  92.     {
  93.       PCLOSE(stream) ;
  94.       IsPopen = FALSE ;
  95.     }
  96.   else
  97. #endif  /* unix */
  98.     FCLOSE(stream) ;
  99. }
  100.  
  101.  
  102. FILE *
  103. EfopenR(filename)
  104. char *filename ;
  105. {
  106.   FILE *istr ;
  107. #if unix
  108.   FILE *popen() ;
  109. #endif /* unix */
  110.  
  111.   DEBUG((Debug, "EfopenR(%s)\n", filename)) ;
  112.   if ((istr = fopen(filename, RMODE)) != NULL) return(istr) ;
  113.  
  114. #if  unix
  115.   if (errno == ENOENT)
  116.     {
  117.       char buf[MAXPATHLEN] ;
  118.  
  119. /* First see if the compressed file exists and is readable */
  120.  
  121.       SPRINTF(buf, "%s.Z", filename) ;
  122.       if ((istr = fopen(buf, "r")) != NULL)
  123.         {
  124.  
  125. /* OK - it's there */
  126.  
  127.           FCLOSE(istr) ;
  128.           SPRINTF(buf, "zcat %s", filename) ;
  129.           DEBUG((Debug, "popen(%s)\n", buf)) ;
  130.           if ((istr = popen(buf, "r")) != NULL)
  131.             {
  132.               IsPopen = TRUE ;
  133.               return(istr) ;
  134.             }
  135.         }
  136.     }
  137. #endif  /* unix */
  138.  
  139.   SPRINTF(ErrBuf, "Can't read file '%s'", filename) ;
  140.   error(ERR_SYS) ;
  141.   return(NULL) ;
  142. }
  143.  
  144.  
  145. FILE *
  146. EfopenW(filename)
  147. char *filename ;
  148. {
  149.   FILE *ostr ;
  150. #ifdef  unix
  151.   FILE *popen() ;
  152. #endif  /* unix */
  153.  
  154.   DEBUG((Debug, "EfopenW(%s)\n", filename)) ;
  155.  
  156. #ifdef  unix
  157.   if (*filename == '|')
  158.     {
  159.       ++filename ;
  160.  
  161.       if ((ostr = popen(filename, "w")) == NULL)
  162.         {
  163.           SPRINTF(ErrBuf, "Can't run command '%s'", filename) ;
  164.           error(ERR_SYS) ;
  165.         }
  166.       IsPopen = TRUE ;
  167.       return ostr ;
  168.     }
  169. #endif  /* unix */
  170.  
  171.   if ((ostr = fopen(filename, WMODE)) == NULL)
  172.     {
  173.       SPRINTF(ErrBuf, "Can't write file '%s'", filename) ;
  174.       error(ERR_SYS) ;
  175.     }
  176.   return(ostr) ;
  177. }
  178.  
  179.  
  180. void
  181. do_ioerror(fd, filename, direction, row)
  182. FILE *fd ;
  183. char *filename, *direction ;
  184. int row ;
  185. {
  186.   if (ferror(fd))
  187.     {
  188.       SPRINTF(ErrBuf, "File '%s' %s error on row %d",
  189.               filename, direction, row) ;
  190.       error(ERR_SYS) ;
  191.       FCLOSE(fd) ;
  192.       return ;
  193.     }
  194.  
  195.   SPRINTF(ErrBuf, "File '%s' insufficient data at row %d", filename, row) ;
  196.   error(0) ;
  197. }
  198.  
  199.  
  200. void
  201. adjust_image(old, newp, nwidth, ncolors)
  202. struct SRC *old ;
  203. pixel_t **newp ;
  204. int nwidth, ncolors ;
  205. {
  206.   int c, n, o, x, y ;
  207.  
  208.   if (old->ncolors == 1)
  209.     {
  210.       if (ncolors == 1)
  211.         for (y = 0; y < old->height; y++)
  212.           {
  213.             o = y * old->width ;
  214.             n = y * nwidth ;
  215.             for (x = 0; x < old->width; x++)
  216.               newp[0][n+x] = old->pix[0][o+x] ;
  217.           }
  218.       else
  219.         for (y = 0; y < old->height; y++)
  220.           {
  221.             o = y * old->width ;
  222.             n = y * nwidth ;
  223.             for (x = 0; x < old->width; x++)
  224.               newp[0][n+x] = newp[0][n+x] = newp[0][n+x] = old->pix[0][o+x] ;
  225.           }
  226.     }
  227.   else
  228.     for (c = 0; c < old->ncolors; c++)
  229.       {
  230.         o = y * old->width ;
  231.         n = y * nwidth ;
  232.         for (x = 0; x < old->width; x++)
  233.           newp[c][n+x] = old->pix[c][o+x] ;
  234.       }
  235. }
  236.  
  237.  
  238. void
  239. getpix(filename, imgname, started)
  240. char *filename ;                      /* File name */
  241. char *imgname ;                       /* Image name */
  242. int started ;
  243. {
  244.   FILE       *fd ;
  245.   struct SRC *img ;                             /* Pointer into Images */
  246.   struct SRC *unused = (struct SRC *) 0 ;       /* First unused slot */
  247.   char       *p ;
  248.   char       *rem ;
  249.   int        len ;
  250.   pixel_t    **tmpOldp, **tmpNewp ;
  251.   int        height, mask, ncolors, off, width, x,y ;
  252.  
  253.   extern int pm_iserror ;
  254.  
  255.   int        format ;
  256.   pixval     maxval ;
  257.   gray       *grayrow ;
  258.   pixel      *pixelrow ;
  259.  
  260.   len = strlen(filename) ;
  261.   if (len > 2 && !strncmp(&filename[len-2], ".Z", 2)) filename[len-2] = '\0' ;
  262.  
  263.   if ((fd = EfopenR(filename)) == NULL) return ;
  264.   pm_iserror  = FALSE ;
  265.   ppm_readppminit(fd, &width, &height, &maxval, &format) ;
  266.  
  267.   if (format == PBM_FORMAT || format == RPBM_FORMAT ||
  268.       format == PGM_FORMAT || format == RPGM_FORMAT)
  269.     {
  270.       ncolors = 1 ;
  271.       grayrow = pgm_allocrow(width) ;
  272.     }
  273.   else if (format == PPM_FORMAT || format == RPPM_FORMAT)
  274.     {
  275.       ncolors = 3 ;
  276.       pixelrow = ppm_allocrow(width) ;
  277.     }
  278.   else if (format == OLD_POPI_FORMAT) ncolors = 1 ;
  279.  
  280.   if (imgname == 0 || *imgname == '\0')
  281.     {
  282.       imgname = filename ;
  283.  
  284. /*
  285.  *  Use the basename of the filename for the image name. If this results in a
  286.  *  non-valid image name, they'll just have to use the $n equivalent. It's not
  287.  *  our business to go transforming names.
  288.  */
  289.  
  290. /* Find last '/' in string */
  291.  
  292.       for (p = rem = imgname; *p; ++p)
  293.         if (*p == '/' && p[1] != '\0') rem = p + 1 ;
  294.  
  295.       imgname = rem ;
  296.     }
  297.  
  298. /* See if the named image already exists */
  299.  
  300.   for (img = Images; img != &Images[nimages]; ++img)
  301.     {
  302.       if (img->str && strcmp(img->str, imgname) == 0) break ;
  303.  
  304.       if (img->pix == (pixel_t **) NULL && unused == (struct SRC *) NULL)
  305.         unused = img ;
  306.     }
  307.  
  308.   if (img == &Images[nimages])
  309.     {
  310.  
  311. /* Named image doesn't exist. Allocate a new image. */
  312.  
  313.       if (unused == (struct SRC *) 0) img = &Images[nimages++] ;
  314.       else img = unused ;
  315.  
  316.       if ((img->pix = ImgAlloc(width, height, ncolors)) == 0 ||
  317.           (img->str = (char *)
  318.                       Emalloc((unsigned int) (strlen(imgname)+1))) == 0)
  319.         return ;
  320.  
  321.       STRCPY(img->str, imgname) ;
  322.     }
  323.   else if (img->width   != width || img->height != height ||
  324.            img->ncolors != ncolors)
  325.     {                          /* Existing image has changed size or depth. */
  326.       ImgFree(img) ;
  327.       if ((img->pix = ImgAlloc(width, height, ncolors)) == 0 ||
  328.           (img->str = (char *)
  329.                       Emalloc((unsigned int) (strlen(imgname)+1))) == 0)
  330.         return ;
  331.  
  332.       STRCPY(img->str, imgname) ;
  333.     }
  334.  
  335.   img->width   = width ;
  336.   img->height  = height ;
  337.   img->ncolors = ncolors ;
  338.   img->Xalloc  = width ;
  339.  
  340. /* Read in the image. */
  341.  
  342.   for (y = 0; y < height; y++)
  343.     {
  344.       mask = (signed_io) ? 0x80 : 0x00 ;
  345.       if (format == PBM_FORMAT || format == RPBM_FORMAT ||
  346.           format == PGM_FORMAT || format == RPGM_FORMAT)
  347.         { 
  348.           pgm_readpgmrow(fd, grayrow, width, maxval, format) ;
  349.           if (pm_iserror == TRUE)
  350.             {
  351.               do_ioerror(fd, filename, "read", y) ;
  352.               return ;
  353.             }
  354.           off = y * width ;
  355.           for (x = 0; x < width; x++)
  356.             img->pix[0][off+x] = (char) (grayrow[x] ^ mask) ;
  357.         }
  358.       else if (format == PPM_FORMAT || format == RPPM_FORMAT)
  359.         {
  360.           ppm_readppmrow(fd, pixelrow, width, maxval, format) ;
  361.           if (pm_iserror == TRUE)
  362.             {
  363.               do_ioerror(fd, filename, "read", y) ;
  364.               return ;
  365.             }
  366.           off = y * width ;
  367.           for (x = 0; x < width; x++)
  368.             {
  369.               img->pix[0][off+x] = pixelrow[x].r ^ mask ;
  370.               img->pix[1][off+x] = pixelrow[x].g ^ mask ;
  371.               img->pix[2][off+x] = pixelrow[x].b ^ mask ;
  372.             }
  373.         }    
  374.       else if (format == OLD_POPI_FORMAT)
  375.         {
  376.           if (fread((char *) img->pix[0][y*width], 1, width, fd) <= 0)
  377.             {
  378.               do_ioerror(fd, filename, "read", y) ;
  379.               return ;
  380.             }
  381.         }
  382.     }
  383.  
  384.        if (format == PGM_FORMAT || format == RPGM_FORMAT ||
  385.            format == PGM_FORMAT || format == RPGM_FORMAT)
  386.     pgm_freerow(grayrow) ;
  387.   else if (format == PPM_FORMAT || format == RPPM_FORMAT)
  388.     ppm_freerow(pixelrow) ;
  389.   Efclose(fd) ;
  390.  
  391. /*  Set the size of the pictures "old" and "new" to the size of the picture
  392.  *  just read. Note: this cannot be :undo(ne). If sizes have changed, throw
  393.  *  away the polar-table (if any).
  394.  */
  395.   if (((CurOld->width != width) || (CurOld->height != height)) && (avals))
  396.     {
  397.       FREE((char *) avals) ;
  398.       FREE((char *) rvals) ;
  399.       avals = NULL ;
  400.       rvals = NULL ;
  401.     }
  402.   CurOld->width = width ;
  403.   CurOld->height = height ;
  404.   CurNew->width = width ;
  405.   CurNew-> height = height ;
  406.  
  407. /*  Check to see if this new image is larger in size or greater in depth than
  408.  *  the current "max" image. If so, then the "new" and "old" images need to
  409.  *  be reallocated, copying across the current information.
  410.  */
  411.  
  412.   if ((ncolors > colors) || (width > Xsize) || (height > Ysize))
  413.     {
  414.       tmpOldp = ImgAlloc((width  > Xsize) ? width  : Xsize,
  415.                          (height > Ysize) ? height : Ysize, ncolors) ;
  416.       adjust_image(CurOld, tmpOldp,
  417.                    (width  > Xsize) ? width  : Xsize, ncolors) ;
  418.  
  419.       tmpNewp = ImgAlloc((width > Xsize)  ? width  : Xsize,
  420.                          (height > Ysize) ? height : Ysize, ncolors) ;
  421.       adjust_image(CurNew, tmpNewp,
  422.                    (width > Xsize)  ? width  : Xsize, ncolors) ;
  423.  
  424.       ImgFree(CurOld) ;
  425.       ImgFree(CurNew) ;
  426.  
  427.       CurOld->pix     = tmpOldp ;          /* Create new "old" image. */
  428.       CurOld->str     = Emalloc((unsigned int) (strlen("old")+1)) ;
  429.       STRCPY(CurOld->str, "old") ;
  430.       CurOld->width   = width ;
  431.       CurOld->height  = height ;
  432.       CurOld->ncolors = ncolors ;
  433.  
  434.       CurNew->pix     = tmpNewp ;          /* Create new "new" image. */
  435.       CurNew->str     = Emalloc((unsigned int) (strlen("new")+1)) ;
  436.       STRCPY(CurNew->str, "new") ;
  437.       CurNew->width   = width ;
  438.       CurNew->height  = height ;
  439.       CurNew->ncolors = ncolors ;
  440.  
  441.       if (width   > Xsize)  Xsize  = width ;
  442.       if (height  > Ysize)  Ysize  = height ;
  443.       if (ncolors > colors) colors = ncolors ;
  444.       CurOld->Xalloc  = Xsize ;
  445.       CurNew->Xalloc  = Xsize ;
  446.  
  447.       if (colors == 3)
  448.         {
  449.           if (ntsc != NULL) FREE((char *) ntsc) ;
  450.           ntsc = (pixel_t *) Emalloc((unsigned) Xsize * sizeof(pixel_t)) ;
  451.         }
  452.       if (started == TRUE) disp_resize(Xsize, Ysize) ;
  453.     }
  454. }
  455.  
  456.  
  457. void
  458. putpix(into, filename)
  459. struct SRC *into ;               /* Work buffer */
  460. char *filename ;                 /* File name */
  461. {
  462.   FILE    *fd ;
  463.   int     mask, off, x, y ;
  464.  
  465.   extern int pm_iserror ;
  466.  
  467.   int        format ;
  468.   pixval     maxval ;
  469.   gray       *grayrow ;
  470.   pixel      *pixelrow ;
  471.  
  472.   if ((fd = EfopenW(filename)) == NULL) return ;
  473.   pm_iserror  = FALSE ;
  474.   maxval = 255 ;
  475.   if (into->ncolors == 1)
  476.     {
  477.       format = RPGM_FORMAT ;
  478.       if (oldfmt != TRUE)
  479.         pgm_writepgminit(fd, into->width, into->height, maxval) ;
  480.       grayrow = pgm_allocrow(into->width) ;
  481.     }
  482.   else if (into->ncolors == 3)
  483.     {
  484.       format = RPPM_FORMAT ;
  485.       ppm_writeppminit(fd, into->width, into->height, maxval) ;
  486.       pixelrow = ppm_allocrow(into->width) ;
  487.     }
  488.  
  489. /* Write out the image. */
  490.  
  491.   for (y = 0; y < into->height; y++)
  492.     {
  493.       mask = (signed_io) ? 0x80 : 0x00 ;
  494.       if (format == RPGM_FORMAT)
  495.         {           
  496.           off = y * into->Xalloc ;
  497.           for (x = 0; x < into->width; x++)
  498.             grayrow[x] = into->pix[0][off+x] ^ mask ;
  499.           pgm_writepgmrow(fd, grayrow, into->width, maxval) ;
  500.           if (pm_iserror == TRUE)
  501.             {       
  502.               do_ioerror(fd, filename, "write", y) ;
  503.               return ;
  504.             }       
  505.         }   
  506.       else if (format == RPPM_FORMAT)
  507.         {           
  508.           off = y * into->Xalloc ;
  509.           for (x = 0; x < into->width; x++)
  510.             {       
  511.               pixelrow[x].r = into->pix[0][off+x] ^ mask ;
  512.               pixelrow[x].g = into->pix[1][off+x] ^ mask ;
  513.               pixelrow[x].b = into->pix[2][off+x] ^ mask ;
  514.             }   
  515.           ppm_writeppmrow(fd, pixelrow, into->width, maxval) ;
  516.           if (pm_iserror == TRUE)
  517.             {       
  518.               do_ioerror(fd, filename, "write", y) ;
  519.               return ;
  520.             }
  521.         }
  522.     }
  523.  
  524.        if (format == RPGM_FORMAT) pgm_freerow(grayrow) ;
  525.   else if (format == RPPM_FORMAT) ppm_freerow(pixelrow) ;
  526.  
  527.   Efclose(fd) ;
  528. }
  529.  
  530.  
  531. void
  532. prntimg(imgname, im)
  533. char *imgname ;
  534. struct SRC *im ;
  535. {
  536.   int i, len ;
  537.  
  538.   len = strlen(imgname) ;
  539.   for (i = 0; i < 40; ++i)
  540.     {
  541.       PRINTF("%c", (i < len) ? imgname[i] : ' ') ;
  542.       if (LogStr)
  543.         FPRINTF(LogStr, "%c", (i < len) ? imgname[i] : ' ') ;
  544.     }
  545.   PRINTF("\t[%d,%d]  (%s)\n", im->width, im->height,
  546.                               (im->ncolors == 1) ? "gray" : "color") ;
  547.   if (LogStr)
  548.     FPRINTF(LogStr, "\t[%d,%d]  (%s)\n", im->width, im->height,
  549.                               (im->ncolors == 1) ? "gray" : "color") ;
  550. }
  551.  
  552.  
  553. void
  554. showfiles()
  555. {
  556.   struct SRC *img ;
  557.   int j ;
  558.   char namestr[MAXLINE] ;
  559.  
  560.   PRINTF("\t\tRange error handling: %s\n", (rng_policy == CUT) ? "cut" :
  561.         (rng_policy == MINMAX) ? "minmax" : "wrap") ;
  562.   if (LogStr)
  563.     FPRINTF(LogStr, "\t\tRange error handling: %s\n",
  564.                     (rng_policy == CUT) ? "cut" :
  565.             (rng_policy == MINMAX) ? "minmax" : "wrap") ;
  566.   prntimg("-previous-", CurNew) ;
  567.   prntimg("-CURRENT-", CurOld) ;
  568.   for (j = 1, img = &Images[2]; j < nimages - 1; ++img, ++j)
  569.     {
  570.       if (img->str)
  571.         {
  572.           SPRINTF(namestr, "$%d = %s", j, img->str) ;
  573.       prntimg(namestr, img) ;
  574.         }
  575.     }
  576. }
  577.